//Copyright (c) Microsoft Corporation. All rights reserved.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Xml;
using System.Drawing;

namespace Microsoft.Office.OneNote
{
	public class Section : HierarchyNode
	{
		public Section()
		{

		}

		public Section(string name)
		{
			this.Name = name;
		}

		/// <summary>
		/// Clones the Section.
		/// </summary>
		/// <returns>A deep copy of this Folder.</returns>
		public override object Clone()
		{
			Section clone = new Section();
			clone.Id = this.Id;

			return clone;
		}

		/// <summary>
		/// Useful for debugging.
		/// </summary>
		/// <returns>A string representation of the Notebook.</returns>
		public override string ToString()
		{
			return this.Name;
		}

		/// <summary>
		/// Tests to see if this Section can contain the specified child node.
		/// </summary>
		/// <param name="child">The child which we are testing.</param>
		/// <returns>Returns true if the child node is of type folder or section.</returns>
		public override bool CanContain(ANode child)
		{
			return (child is Page);
		}

		/// <summary>
		/// Used while committing all pending additions to commit any newly created
		/// node to OneNote.
		/// </summary>
		/// <param name="serializedId">The new ID of this node.</param>
		protected internal override void AddHierarchyToOneNote(out string serializedId)
		{
			Debug.Assert(this.Id == ObjectId.Empty);

			// Create the section via OpenHierarchy:
			string parentId = this.ParentHierarchyNode.Id.ToString();

			string path = this.Path;
			if (path == "")
			{
				path = this.Name;
			}

			if (!path.EndsWith(".one"))
				path = path + ".one";

			Application.Server.OpenHierarchy(path, parentId, out serializedId, CreateFileType.Section);
		}

		/// <summary>
		/// Serializes the <see cref="Section"/> object to Xml in a format
		/// suitable for import into OneNote.
		/// </summary>
		/// <param name="parentNode">
		/// A reference to the parent XML node that we should serialize ourselves
		/// as a child of.
		/// </param>
		/// <param name="deep">
		/// Should we recursively serialize our children?
		/// </param>
		/// <returns>
		/// The serialized node.
		/// </returns>
		protected internal override XmlNode SerializeToXml(XmlNode parentNode, bool deep)
		{
			XmlDocument document = parentNode as XmlDocument;
			if (document == null)
				document = parentNode.OwnerDocument;

			XmlElement serialized = document.CreateElement("Section", OneNote.ApplicationServer.XmlNamespace);
			serialized.SetAttribute("ID", this.Id.ToString());
			serialized.SetAttribute("name", this.Name);
			serialized.SetAttribute("path", this.Path);

			string serializedColor = "none";
			if (this.Color != Color.Empty)
				serializedColor = ColorTranslator.ToHtml(Color.FromArgb(this.Color.ToArgb()));
			serialized.SetAttribute("color", serializedColor);

			parentNode.AppendChild(serialized);

			if (deep)
			{
				foreach (ANode child in children)
				{
					child.SerializeToXml(serialized, deep);
				}
			}

			return serialized;
		}

		/// <summary>
		/// Deserializes the <see cref="Section"/> object from OneNote's xml 
		/// representation.
		/// </summary>
		/// <param name="node">
		/// A reference to the XML node that we should deserialize ourselves
		/// from.
		/// </param>
		protected internal override void DeserializeFromXml(XmlNode node)
		{
			XmlElement element = (XmlElement) node;

			// Set properties:
			this.Name = element.GetAttribute("name");
			this.Path = element.GetAttribute("path");
			if (element.HasAttribute("color") && element.GetAttribute("color") != "none")
				this.Color = ColorTranslator.FromHtml(element.GetAttribute("color"));

			// Process children:
			if (HierarchyXmlHelper.NodeChildrenAreLoaded(element))
			{
				foreach (XmlNode child in element.ChildNodes)
				{
					XmlElement childElement = child as XmlElement;
					if (childElement == null)
						continue;

					HierarchyNode deserialized = null;
					switch (childElement.LocalName)
					{
						case "Page":
							deserialized = new Page();
							break;

						default:
							// Unrecognized element child
							Debug.Assert(false);
							break;
					}

					if (deserialized != null)
					{
						deserialized.DeserializeFromXml(childElement);
						children.Add(deserialized);
					}
				}
			}

			base.DeserializeFromXml(node);
		}

		public string Name
		{
			get { return GetProperty_Else("name", ""); }
			set { SetProperty("name", value); }
		}

		public string Path
		{
			get { return GetProperty_Else("path", ""); }
			set { SetProperty("path", value); }
		}

		public Color Color
		{
			get { return GetProperty_Else("color", Color.Empty); }
			set { SetProperty("color", value); }
		}
	}
}
